from odoo.http import request, Response
from odoo import http
from odoo.addons.api_manager.tools.check_token import check_token
from odoo.addons.api_manager.tools.create_records import create_records
import logging
import json
from odoo import fields, _
from odoo.exceptions import ValidationError

_logger = logging.getLogger(__name__)


class ApiMrpProduction(http.Controller):
    """
    q1: 当前工序如果，odoo系统物料库存不足，是否能够过数
    q2: 非当前工工序，系统过数如何处理
    """
    @http.route("/v1.0/sb_api/mrp_workorder/todo", auth='public', type='http', methods=['post'], csrf=False)
    @check_token
    def mrp_workorder_todo(self, **kwargs):
        """自动过数
        当前工序报废：直接生成报废单据
        历史工序报废：跳过odoo的校验逻辑再生成报废
        """
        _logger.info('开始自动过数...')
        data = request.httprequest.get_json()
        result = {
            'json': True,
            'data': {}
        }
        api_result = {
            'code': 0,
            'message': 'success'
        }
        params = data.get('params')
        # public user，无法过数，使用admin
        request.env.uid = 2
        try:
            production_code = params.get('production_code')
            # --------- 报废处理逻辑 ----------------
            scraps = params.get('scraps', [])
            for s in scraps:
                if not s.get('workorder_code', False) or not s.get('scrap_workcenters', False):
                    raise ValidationError('报废申请：workorder_code 或 scrap_workcenters, 不能为空')

                if not s.get('mes_code', False):
                    raise ValidationError('mes_code不能为空')
                alert = request.env['quality.alert'].search([('s_mes_code', '=', s.get('mes_code', False))])
                if alert:
                    raise ValidationError("mes_code必须唯一，odoo已存在{}的报废申请".format(s.get('mes_code', False)))

                wo = self.get_workorder(production_code, s.get('workorder_code'))
                if wo.state in ['done', 'cancel']:
                    raise ValidationError('当前工序状态{}，不能进行报废'.format(wo.state))

                workorder_qty_wip = wo.qty_wip
                if not workorder_qty_wip:
                    raise ValidationError('工序:{},在制数不足，无法进行报废'.format(wo.id))

                s_panel_pcs = wo.value_pnl
                s_set_pcs = wo.value_set
                s_scrap_vals = []
                # 报废责任工序
                for r in s.get('scrap_workcenters'):
                    wc = request.env['mrp.workcenter'].sudo().search([('code', '=', r.get('workcenter_code'))])
                    sr = request.env['scrap.reason'].sudo().search([('code', '=', r.get('scrap_code'))])
                    if not sr:
                        sr = request.env['scrap.reason'].sudo().create({'code': r.get('scrap_code'),
                                                                        'name': r.get('scrap_reason'),
                                                                        'en_name': r.get('scrap_en_name','')})
                    if not wc:
                        raise ValidationError('odoo未找到编码为：{} 的责任工序'.format(r.get('workcenter_code')))

                    if not sr:
                        raise ValidationError('报废原因未找到或创建失败：{}'.format(r.get('scrap_reason')))
                    qty_reject_pcs = int(r.get('qty_reject_pcs', 0))
                    qty_reject_set = int(r.get('qty_reject_set', 0))
                    qty_reject_pnl = int(r.get('qty_reject_pnl', 0))
                    if not qty_reject_pcs and qty_reject_set:
                        qty_reject_pcs = qty_reject_set * s_set_pcs
                    elif not qty_reject_pcs and qty_reject_pnl:
                        qty_reject_pcs = qty_reject_pnl * s_panel_pcs
                    if not qty_reject_pcs and not qty_reject_set and not qty_reject_pnl:
                        raise ValidationError('qty_reject_pcs、qty_reject_set、qty_reject_pnl至少有一个不为0')
                    s_scrap_vals.append((0, 0, {
                        'workorder_id': wo.id,
                        'scrap_workcenter_id': wc.id,
                        'scrap_reason_id': sr.id,
                        'scrap_qty': qty_reject_pcs,
                        'scrap_set_qty': qty_reject_set,
                        'scrap_panel_qty': qty_reject_pnl,
                    }))
                alert_vals = {
                    's_production_id': wo.production_id.id,
                    'description': 'Mes -> Odoo',
                    's_workorder_id': wo.id,
                    's_work_station_id': wo.workcenter_id.work_station_id.id,
                    'workcenter_id': wo.workcenter_id.id,
                    's_qty_wip': wo.qty_wip,
                    's_qty_wip_set': wo.qty_wip_set,
                    's_qty_wip_pnl': wo.qty_wip_pnl,
                    'product_id': wo.production_id.product_id.id,
                    'product_tmpl_id': wo.production_id.product_id.product_tmpl_id.id,
                    's_scrap_ids': s_scrap_vals,
                    's_mes_code': s.get('mes_code')
                }
                # 工序报废
                alert_id = request.env['quality.alert'].with_context(skip_constrains=True).create(alert_vals)
                alert_id.with_context(skip_constrains=True).action_confirm()

            if not scraps:
                workorder_code = params.get('workorder_code')
                # ---------- 过数处理逻辑 ----------------
                qty_produced_pnl = int(params.get('qty_produced_pnl', 0))
                qty_produced_pcs = int(params.get('qty_produced_pcs', 0))
                qty_produced_set = int(params.get('qty_produced_set', 0))
                if qty_produced_pcs and qty_produced_pnl and qty_produced_pcs:
                    a_wo = self.get_workorder(production_code, workorder_code)
                    if a_wo.state in ['pending',  'cancel']:
                        raise ValidationError('当前工序状态{}不能进行过数'.format(a_wo.state))
                    elif a_wo.state == 'ready':
                        a_wo.button_start()
                    # erp 过数完成的不对mes做卡控
                    if a_wo.state != 'done':
                        rec = a_wo.with_context(auto_finish=True).button_finish()
                        rec.qty_produced_pnl = qty_produced_pnl
                        rec.qty_produced_set = qty_produced_set
                        rec.qty_produced = qty_produced_pcs
                        if a_wo.workcenter_id.is_date_code and not params.get('datacodes', []):
                            raise ValidationError(f'当前工序[{a_wo.name}], 需要周期码')
                        elif a_wo.workcenter_id.is_date_code and params.get('datacodes', []):
                            rec.write({
                                'date_code_ids': [(0, 0, {
                                    'date_code': d['datecode'],
                                    'qty': d['qty']
                                }) for d in params.get('datacodes', [])]
                            })
                        rec.with_context(auto_unfinish=True, auto_mes=True).done_move_qty()
                        # rec.done_move_qty()
                        if a_wo.state == 'done':
                            if a_wo.is_last_unfinished_wo:
                                a_wo.production_id.with_context(skip_consumption=True).button_mark_done()
                                a_wo.production_id.is_autocomplete = True
                                # 更新批次
                                a_wo._update_batch()
                            # 完成物料消耗
                            a_wo.consumable_materials()
                else:
                    raise ValidationError('qty_produced_pcs, qty_produced_pnl, qty_produced_set 不能为空')
        except Exception as e:
            api_result['code'] = -1
            api_result['message'] = '{}'.format(e)
            request.env.cr.rollback()

        result['data'] = api_result
        result_json = json.dumps(result, ensure_ascii=False)
        create_records(result_json)
        return Response(result_json)

    def get_workorder(self, production_code, workorder_code):
        sql = """
                SELECT mw.id FROM mrp_workorder as mw, mrp_production as mp, mrp_workcenter as mc  
                WHERE mw.production_id=mp.id
                and mw.workcenter_id=mc.id
                and mp.name='{}'
                and mc.code='{}';
            """.format(production_code, workorder_code)
        cr = request.env.cr
        cr.execute(sql)
        wid = cr.fetchall()
        if not wid:
            raise ValidationError('未查询到相关工序: {}-{}'.format(production_code, workorder_code))
        if len(wid) > 1:
            raise ValidationError('查询到工序不唯一：{}-{}'.format(production_code, workorder_code))
        wo = request.env['mrp.workorder'].sudo().search([('id', '=', list(wid[0])[0])])
        return wo
